package gee

import (
	"fmt"
	"log"
	"net/http"
)

// HandlerFunc HandlerFunc定义gee使用的请求处理程序
type HandlerFunc func(http.ResponseWriter, *http.Request)

// Engine 实现ServeHTTP接口
type Engine struct {
	router map[string]HandlerFunc
}

// New 是gee.Engine的构造函数
func New() *Engine {
	//在编程中，情况与上述类比类似。使用make函数创建的变量是动态分配的，可以根据需要自动调整大小，并立即使用。
	//而使用var声明创建的变量是静态分配的，需要自己初始化，适用于预先知道大小并且不需要动态调整大小的情况。这两种方法在不同的情境下都有其优势和用途，取决于你的编程需求。
	return &Engine{router: make(map[string]HandlerFunc)}
}

// addRoute adds a route to the engine
func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
	key := method + "-" + pattern
	log.Printf("路由添加成功，等待请求。Route %4s - %s", method, pattern)
	engine.router[key] = handler
}

// GET defines the method to add GET request
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
	engine.addRoute("GET", pattern, handler)
}

// POST 定义添加POST请求的方法
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
	engine.addRoute("POST", pattern, handler)
}

// Run (*Engine).Run()方法，是 ListenAndServe 的包装。
func (engine *Engine) Run(addr string) (err error) {
	return http.ListenAndServe(addr, engine)
}

// 首先进来这里
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	key := req.Method + "-" + req.URL.Path
	//Engine实现的 ServeHTTP 方法的作用就是，解析请求的路径，查找路由映射表，如果查到，就执行注册的处理方法。如果查不到，就返回 404 NOT FOUND 。
	if handler, ok := engine.router[key]; ok {
		handler(w, req) // 进方法了！
	} else {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
	}
}
